package com.qili.service.it.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.qili.entity.base.BaseDict;
import com.qili.entity.base.Col;
import com.qili.entity.base.FormType;
import com.qili.entity.supervisor.SupervisorFile;
import com.qili.entity.supervisor.SupervisorFileTemp;
import com.qili.entity.supervisor.SupervisorProjectForms;
import com.qili.entity.supervisor.dto.SupervisorProjectFromsDTO;
import com.qili.service.base.BaseDictService;
import com.qili.service.it.FormBaseService;
import com.qili.service.supervisor.SupervisorFileService;
import com.qili.service.supervisor.SupervisorFileTempService;
import com.qili.service.supervisor.SupervisorProjectFormsDataService;
import com.qili.service.supervisor.SupervisorProjectFormsService;
import com.qili.util.CommonUtil;
import com.qili.util.DateUtil;
import com.qili.util.ReType;
import com.qili.util.StringUtil;
import lombok.extern.java.Log;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
import tk.mybatis.mapper.entity.Example;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.*;

/**
 * @author liuyang
 * @date 2021/4/2
 * @description
 */
@Log
@Service("FormBaseService")
public class FormBaseServiceImpl implements FormBaseService {

    @Autowired
    ShuZhuFormServiceImpl shuZhuFormService;
    @Autowired
    LunWenFormServiceImpl lunWenFormService;
    @Autowired
    ZhuanliFormServiceImpl zhuanliFormService;
    @Autowired
    SupervisorProjectFormsService formsService;
    @Autowired
    SupervisorProjectFormsDataService formsDataService;
    @Autowired
    ItDicServiceImpl dicService;
    @Autowired
    BaseDictService dictService;
    @Autowired
    SupervisorFileTempService fileTempService;
    @Autowired
    SupervisorFileService fileService;
    @Autowired
    ZhengzhongBZFormServiceImpl zhengzhongBZFormService;
    @Autowired
    RuanZhuFormServiceImpl ruanZhuFormService;
    @Autowired
    JiChengDianLuFormServiceImpl jiChengDianLuFormService;
    @Autowired
    KeYanXiangMuFormServiceImpl keYanXiangMuFormService;

    /**
     * 保存保单数据
     * @param forms
     * @param ifNew
     */
    @Override
    public void saveFormData(SupervisorProjectFromsDTO forms, boolean ifNew) {
        getHandler(forms.getSpfF30()).saveFormData(forms,ifNew);
    }

    /**
     * 保存表单文件
     * @param forms
     * @param ifNew
     */
    @Override
    public void saveFormFile(SupervisorProjectFromsDTO forms, boolean ifNew) {
        getHandler(forms.getSpfF30()).saveFormFile(forms,ifNew);
    }

    /**
     * 获取表单数据
     * @param formTypeCode
     * @param formDto
     * @param model
     */
    @Override
    public void getFormData(String formTypeCode, SupervisorProjectFromsDTO formDto, Model model) {
        if(StringUtils.isBlank(formTypeCode)){
            log.warning("获取表单数据时,formTypeCode为空!");
            return ;
        }
        getHandler(formTypeCode).getFormData(formTypeCode,formDto,model);
    }

    /**
     * 根据文件类型获取需要存放的文件路径:
     *
     * @param fileTemp
     * @param formDto
     * @return  例如:xxx/知识产权库/专利/2021_001_xxx专利/技术交底书/
     */
    protected String getFormFilePath(SupervisorFileTemp fileTemp, SupervisorProjectFromsDTO formDto){
        //获取表单核心目录文件对象
        SupervisorFile formCenterDic = (SupervisorFile)formDto.getObj1();
        String formTypeCode = formDto.getSpfF30();
        String formFileTypeCode = fileTemp.getType();
        return getFormFilePath(formCenterDic,formTypeCode,formFileTypeCode);
//        StringBuffer realPath = new StringBuffer();
//        String formCenterDicPath = formCenterDic.getUrl().trim();
//        realPath.append(formCenterDicPath);
//        if(!formCenterDicPath.endsWith(File.separator)){
//            realPath.append(File.separator);
//        }
//        if("110001".equals(formDto.getSpfF30())){
//            //正中参编标准,直接放在正中参编标准文件夹下面,所以不需要拼接什么
//        }else{
//            //获取表单文件类型名称,例如 专利/软著
//            BaseDict baseDict = new BaseDict();
//            baseDict.setBadtTypecode("WJ001");
//            baseDict.setBadtNote("IT-FORM-FILE");
//            baseDict.setBadtCode(fileTemp.getType());
//            List<BaseDict> select = dictService.select(baseDict);
//            if(CollectionUtil.isNotEmpty(select)){
//                BaseDict formFileDict = select.get(0);
//                String formFileTypeName = formFileDict.getBadtName();
//                realPath.append(formFileTypeName)
//                        .append(File.separator);
//            }else{
//                throw new RuntimeException("请先设置IT知识库表单文件类型名称");
//            }
//        }
//        return realPath.toString();
    }

    public String getFormFilePath(SupervisorFile formCenterFile,String formTypeCode,String formFileTypeCode){
        StringBuffer realPath = new StringBuffer();
        String formCenterDicPath = formCenterFile.getUrl().trim();
        realPath.append(formCenterDicPath);
        if(!formCenterDicPath.endsWith(File.separator)){
            realPath.append(File.separator);
        }
        if("110001".equals(formTypeCode)){
            //正中参编标准,直接放在正中参编标准文件夹下面,所以不需要拼接什么
        }else{
            //获取表单文件类型名称,例如 专利/软著
            BaseDict baseDict = new BaseDict();
            baseDict.setBadtTypecode("WJ001");
            baseDict.setBadtNote("IT-FORM-FILE");
            baseDict.setBadtCode(formFileTypeCode);
            List<BaseDict> select = dictService.select(baseDict);
            if(CollectionUtil.isNotEmpty(select)){
                BaseDict formFileDict = select.get(0);
                String formFileTypeName = formFileDict.getBadtName();
                realPath.append(formFileTypeName)
                        .append(File.separator);
            }else{
                throw new RuntimeException("请先设置IT知识库表单文件类型名称");
            }
        }
        return realPath.toString();
    }

    @Override
    public void setFormFiles(String formTypeCode, SupervisorProjectFromsDTO formDto) {

        FormType formType = FormType.getFormType(formTypeCode);
        //查询表单主要文件夹:
        SupervisorFile formCenterFileSelect = new SupervisorFile();
        formCenterFileSelect.setLinkId(formDto.getSpfId());
        formCenterFileSelect.setZskfileType("1");
        formCenterFileSelect.setType(formTypeCode);
        List<SupervisorFile> select = fileService.select(formCenterFileSelect);
        SupervisorFile formCenterFile = null;
        if(CollectionUtil.isNotEmpty(select)){
            formCenterFile = select.get(0);
        }
        if(formCenterFile == null && !"110001".equals(formTypeCode)){
            log.warning("获取表单对应的文件时,没有获取到表单主要文件夹,表单id:"+formDto.getSpfId());
            return ;
        }
        Integer fileCount = 1;
        switch (formType){
            case ZZCBBZ:
                fileCount = 1;
                break;
            case ZL:
                fileCount = 6;
                break;
            case RZ:
                fileCount = 5;
                break;
            case JCDLBT:
                fileCount = 1;
                break;
            case LW:
                fileCount = LunWenFormServiceImpl.FILE_COUNT;
                break;
            case SZ:
                fileCount = 2;
                break;
            case KYXMK:
                fileCount = KeYanXiangMuFormServiceImpl.FILE_COUNT;
                break;
        }
        for(int i=1;i<fileCount+1;i++){
            Example example = new Example(SupervisorFile.class);
            String back = StringUtil.autoGenericCode(i + "", 4);
            example.and().andEqualTo("type",formTypeCode+back)
                    .andEqualTo("linkId","110001".equals(formTypeCode) ? formDto.getSpfId() : formCenterFile.getId())
                    .andEqualTo("deleteState","1")
                    .andEqualTo("zskfileType","2");
            List<SupervisorFile> supervisorFiles = fileService.selectByExample(example);
            try {
                Field f = formDto.getClass().getDeclaredField("fileList" + i);
                f.setAccessible(true);
                f.set(formDto,supervisorFiles);
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 获取保存文件夹名称,例如:   2021_001_xxxx专利
     * @param dicId
     * @return
     */
    protected String getOrderDicName(String dicId,String formDataName){
        //1.年份
        Calendar date = Calendar.getInstance();
        String year = String.valueOf(date.get(Calendar.YEAR));
        //2.查询当前文件夹下面有几个文件夹:
        SupervisorFile files = new SupervisorFile();
        files.setSuperiorId(dicId);
        files.setZskfileType("1");
        int i = dicService.selectCount(files)+1;
        String middle = StringUtil.autoGenericCode(i + "", 3);
        StringBuffer sb = new StringBuffer();
        sb.append(year)
                .append("_")
                .append(middle)
                .append("_")
                .append(formDataName);
        return sb.toString();
    }

    /**
     * 如果有同名文件,那么重命名,
     * 如果没有重名文件,那么判断文件夹是否存在,不存在创建,返回该文件
     * @param file
     * @return  返回文件
     */
    protected File checkFileName(File file){
        if(file.exists()){
            String path = file.getPath();
            String fileName = path.substring(path.lastIndexOf(File.separator));
            System.out.println(fileName);
            String newFilePath = "";
            if(fileName.contains("_")){
                String _front = path.substring(0,path.lastIndexOf("_")+1);
                String _back = fileName.substring(fileName.lastIndexOf("."));
                String number = fileName.substring(fileName.lastIndexOf("_")+1,fileName.lastIndexOf("."));
                if(StringUtils.isNumeric(number)){
                    Integer oldNumber = Integer.valueOf(number);
                    oldNumber++;
                    newFilePath = _front + oldNumber+_back;
                }
            }else{
                String fileSuffix = path.substring(path.lastIndexOf("."));
                String _front = path.substring(0,path.lastIndexOf("."));
                newFilePath = _front + "_1"+fileSuffix;
            }
            return checkFileName(new File(newFilePath));
        }else{
            try {
                File fileParent = file.getParentFile();
                if(!fileParent.exists()){
                    fileParent.mkdirs();
                }
                boolean newFile = file.createNewFile();
                if(!newFile){
                    log.warning("创建新文件失败");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return file;
        }
    }

    /**
     * 该方法应该只有表单顶级目录创建表单时调用
     * 生成表单核心文件夹
     * 核心文件夹既可以看做一个表单
     * 里面的每个文件夹都是对应的一种文件类型
     * 该方法为创建表单对应的文件夹
     * @param formDto
     * @return
     */
    protected void createCenterDic(SupervisorProjectFromsDTO formDto){
        if(formDto == null || StringUtils.isBlank(formDto.getSpfF29())){
            log.warning("创建表单核心文件夹时,没有获取到当前所在文件夹!");
        }
        //获取当前所在文件夹信息: 例如: /知识产权库/专利/
        SupervisorFile supervisorFile = dicService.selectByPrimaryKey(formDto.getSpfF29());
        String dicUrl = supervisorFile.getUrl();
        File dicFile = new File(dicUrl);
        dicUrl = dicFile.getPath();
        StringBuffer realPath = new StringBuffer();
        realPath.append(dicUrl);
        if(!dicUrl.endsWith(File.separator)){
            realPath.append(File.separator);
        }
        //获取  年份_xxx_xxxxx专利
        String orderDicName = getOrderDicName(formDto.getSpfF29(), formDto.getSpfF1());
        realPath.append(orderDicName);
        String centerDicPath = realPath.toString();
        //新建系统文件夹:
        File centerDic = new File(centerDicPath);
        if(!(centerDic.exists() && centerDic.isDirectory())){
            if(!centerDic.mkdir()){
                log.warning("创建表单核心文件夹失败!");
            }
        }
        SupervisorFile centerDicFile = new SupervisorFile();
        centerDicFile.setUrl(centerDic.getPath());
        centerDicFile.setZskfileType("1");
        List<SupervisorFile> select1 = dicService.select(centerDicFile);
        if(CollectionUtil.isEmpty(select1)){
            centerDicFile.setCreateBy(CommonUtil.getUserId());
            centerDicFile.setCreateDate(new Date());
            centerDicFile.setFileName(orderDicName);
            centerDicFile.setDeleteState("1");
            centerDicFile.setZskfileType("1");
            centerDicFile.setExamineUser(supervisorFile.getExamineUser());
            centerDicFile.setCanotSeeRoles(supervisorFile.getCanotSeeRoles());
            centerDicFile.setSuperiorId(formDto.getSpfF29());
            centerDicFile.setLinkId(formDto.getSpfId());
            centerDicFile.setFormCenter("1");
            //表单核心文件夹保存当前表单类型编码
            centerDicFile.setType(formDto.getSpfF30());
            dicService.insertSelective(centerDicFile);
            formDto.setObj1(centerDicFile);
        }else{
            formDto.setObj1(select1.get(0));
        }
    }

    /**
     * 移动临时文件,如果目标目录里面有同名文件,那么添加后缀
     * @param tempFile
     * @param formDto
     * @return 移动后的文件
     */
    public File moveTempFile(SupervisorFileTemp tempFile, SupervisorProjectFromsDTO formDto) {
        try {
            String fileName = tempFile.getFileName();
            //1.根据文件类型,生成需要新生成的文件路径
            String targetFileDicPath = getFormFilePath(tempFile, formDto);
            //2.移动操作系统文件
            File targetFile = new File(targetFileDicPath,fileName);
            //如果目标文件存在,那么重命名:(为了renameTo方法的成功)
            targetFile = checkFileName(targetFile);
            File sourceFile = new File(tempFile.getUrl());
            Files.move(Paths.get(sourceFile.getPath()), Paths.get(targetFile.getPath()), StandardCopyOption.REPLACE_EXISTING);
            return targetFile;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    private FormBaseServiceImpl getHandler(String formTypeCode){
        switch (formTypeCode){
            case "110001":
                //标准规范库
                return zhengzhongBZFormService;
            case "110002":
                //专利
                return zhuanliFormService;
            case "110003":
                //软著
                return ruanZhuFormService;
            case "110004":
                //集成电路布图设计
                return jiChengDianLuFormService;
            case "110005":
                //论文
                return lunWenFormService;
            case "110006":
                //书著
                //获取主编:
                return shuZhuFormService;
            case "110007":
                //科研项目库
                return keYanXiangMuFormService;
        }
        return null;
    }


    @Override
    public String getFormCenterFileId(String dicId) {
        SupervisorFile supervisorFile = dicService.selectByPrimaryKey(dicId);
        if(null == supervisorFile){
            return null;
        }
        if("1".equals(supervisorFile.getFormCenter())){
            return supervisorFile.getId();
        }else{
            if(StringUtils.isNotBlank(supervisorFile.getSuperiorId())){
                return getFormCenterFileId(supervisorFile.getSuperiorId());
            }else{
                return "";
            }
        }
    }

    @Override
    public String getExportExcelName(String formTypeCode) {
        FormType formType = FormType.getFormType(formTypeCode);
        String exportExcelName = "";
        switch (formType){
            case ZZCBBZ:
                exportExcelName = "正中参编标准台账_"+ DateUtil.getCurrentDateNoSpliter();
                break;
            case ZL:
                exportExcelName = "专利台账_"+ DateUtil.getCurrentDateNoSpliter();
                break;
            case RZ:
                exportExcelName = "软著台账_"+ DateUtil.getCurrentDateNoSpliter();
                break;
            case JCDLBT:
                exportExcelName = "集成电路布图台账_"+ DateUtil.getCurrentDateNoSpliter();
                break;
            case LW:
                exportExcelName = "论文台账_"+ DateUtil.getCurrentDateNoSpliter();
                break;
            case SZ:
                exportExcelName = "书著台账_"+ DateUtil.getCurrentDateNoSpliter();
                break;
            case KYXMK:
                exportExcelName = "科研项目台账_"+ DateUtil.getCurrentDateNoSpliter();
                break;
        }
        return exportExcelName;
    }

    @Override
    public String getExportExcelName(String formTypeCode, SupervisorProjectFromsDTO formDto, String index) {
        FormType formType = FormType.getFormType(formTypeCode);
        String exportExcelName = "";
        String type = "";
        switch (formType){
            case ZZCBBZ:
                switch (index){
                    case "0":
                        type="按标准名称统计";
                        break;
                    case "1":
                        type="按正中角色统计";
                        break;
                }
                exportExcelName = "标准台账_"+ type +"_" + DateUtil.getCurrentDateNoSpliter();
                break;
            case ZL:
                switch (index){
                    case "0":
                        type="按人统计";
                        break;
                    case "1":
                        type="按权利要求书统计";
                        break;
                    case "2":
                        type="按时间统计";
                        break;
                }
                exportExcelName = "专利台账_" + type +"_" + DateUtil.getCurrentDateNoSpliter();
                break;
            case RZ:
                exportExcelName = "软著台账_软著总篇数统计_"+ DateUtil.getCurrentDateNoSpliter();
                break;
            case JCDLBT:
                exportExcelName = "集成电路布图台账"+ DateUtil.getCurrentDateNoSpliter();
                break;
            case LW:
                //统计类型

                switch (index){
                    case "0":
                        type="按人统计";
                        break;
                    case "1":
                        type="按挂项目统计";
                        break;
                    case "2":
                        type="按论文名称统计";
                        break;
                    case "3":
                        type="按时间统计";
                        break;
                }
                exportExcelName = "论文台账_" + type + "_" + DateUtil.getCurrentDateNoSpliter();
                break;
            case SZ:
                switch (index){
                    case "0":
                        type="按人统计";
                        break;
                    case "1":
                        type="按书著名称统计";
                        break;
                }
                exportExcelName = "书著台账_"+ type + "_" +DateUtil.getCurrentDateNoSpliter();
                break;
            case KYXMK:
                //统计类型
                switch (index){
                    case "0":
                        type="按计划统计";
                        break;
                    case "1":
                        type="按项目级别统计";
                        break;
                    case "2":
                        type="按项目负责人统计";
                        break;
                    case "3":
                        type="按人员统计";
                        break;
                }
                exportExcelName = "科研项目台账_"+type+"_"+ DateUtil.getCurrentDateNoSpliter();
                break;
        }
        return exportExcelName;
    }

    @Override
    public ReType selectFormStatisticsTableData(String formTypeCode, SupervisorProjectFromsDTO formInfo, String index, String page, String limit) {
        return getHandler(formTypeCode).selectFormStatisticsTableData(formTypeCode,formInfo,index,page,limit);
    }

    @Override
    public List<Col> getFormStatisticstableHead(String formTypeCode, SupervisorProjectFromsDTO formInfo, String index) {
        return getHandler(formTypeCode).getFormStatisticstableHead(formTypeCode,formInfo,index);
    }

    public SupervisorProjectFromsDTO changeToDto(SupervisorProjectForms aForm) {
        String aFormJsonStr = JSON.toJSONString(aForm);
        return JSON.parseObject(aFormJsonStr, SupervisorProjectFromsDTO.class);
    }

    public Map changeFormToMap(SupervisorProjectForms aForm){
        if(aForm != null) {
            return JSON.parseObject(JSON.toJSONString(aForm), new TypeReference<Map<String, String>>() {
            });
        }
        return null;
    }
}
